/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "stm32g0xx_hal.h"
#include "sensor.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t g_sensor_type=0xFF; //传感器类型
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
uint8_t Detect_Sensor_Type(void);
uint8_t CalcCrc(uint8_t data[2]);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

uint16_t ccr1_cnt = 0;                   /* 发生第一次下升沿捕获时CCR1的值 */
uint16_t ccr2_cnt = 0;					 /* 发生第二次上升沿捕获时CCR1的值 */
uint16_t Period_cnt = 0;				 /* 发生计数器溢出事件的次数（过渡用） */
uint16_t Period_cnt1 =0;				 /* 发生计数器溢出事件的次数--计数1 */
uint16_t Period_cnt2 = 0;				 /* 发生计数器溢出事件的次数--计数2 */
uint16_t ic_flag = 0;					 /* 输入捕获标志 */
uint16_t end_flag = 0;					 /* 捕获结束标志 */
float frequency,duty_cycle;				     /* 频率 占空比*/

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
	uint8_t i;
	uint16_t cnt=0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_I2C2_Init();
  MX_TIM1_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */

  uint16_t adc_result = 0;
  float co_val = 0.0f;
  char ADC_message[50];
  sensor_init(1);
  HAL_ADC_Start(&hadc1); 	// 等待ADC稳定









  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */


////////////////////////////////////////////UART串口——传感器类型///////////////////////////////////////////////////////////////
//		i = Detect_Sensor_Type();
		i = 2; //调试用!!!!!!!!
		if(i != g_sensor_type){
			g_sensor_type = i;
			sensor_init(i);
		}
		//按照传感器类型处理
		sensor_loop(g_sensor_type);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////FAN-风扇调速读速//////////////////////////////////////////////////////////////////////////////
		read_frequency_dutycycle(&frequency,&duty_cycle);	//读取风扇频率和占空比。变量为字符串格式

		printf("\r\n freq = %.2f Hz,duty_cyc = %.2f %%",frequency,duty_cycle);
		__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 100);//调整风扇转速，1-400，数值越小速度越大

		 HAL_Delay(10000);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////ADC_CO 读取CO值///////////////////////////////////////////////////////////////////////////////////
				if(0 == (cnt % 20)){
				adc_result = HAL_ADC_GetValue(&hadc1);
				co_val = ((float)adc_result * 995) / 4095;// 转换为CO浓度值，注意使用浮点数进行计算

				sprintf(ADC_message, "ADC: %u analog, CO: %.1f ppm\r\n", adc_result, co_val);
				HAL_UART_Transmit(&huart2, (uint8_t*) ADC_message, strlen(ADC_message), 20);
				}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    HAL_Delay(1);
    cnt++;
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void read_frequency_dutycycle(float *frequency,float *duty_cycle){
	if(end_flag){																										 /* 判断是否结束 */
		*duty_cycle=(float)(Period_cnt1 * 65536 + ccr1_cnt + 1) * 100 /(Period_cnt2 * 65536 + ccr2_cnt + 1);  /* 计算占空比 */
		*frequency=1000000 / (float)(Period_cnt2 * 65536 + ccr2_cnt + 1); /* 计算频率 */\
		float FAN_RPM = 60 / *frequency;
		end_flag = 0;																										 /* 将捕获结束标志置0（准备下一次捕获） */
		}
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){    /* 定时器计数溢出回调函数 */
		Period_cnt ++;								            /* 定时器计数溢出时间次数 */
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){	    /* 定时器输入捕获回调函数 */
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){		    /* 判断是不是定时器TIM1 */
			if(end_flag == 0){							        /* 判断结束标志是不是0，在打印期间不进行捕获，防止打印时相关数值改变 */
				switch(ic_flag){							    /* 判断此时处于捕获的第几个阶段 */
					case 0:									    /* 阶段一：第一次捕获到上升沿 */
					{
						__HAL_TIM_SET_COUNTER(&htim3,0);	    /* 将定时器3计数设置为0 */
						ccr1_cnt = 0;							/* 将相关参数清0 */
						ccr2_cnt =0;
						Period_cnt = 0;
						Period_cnt1 = 0;
						Period_cnt2 = 0;
						__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);/* 设置成下降沿捕获 */
						ic_flag = 1;							/* 捕获设置为等待第二个阶段 */
						break;
					}
						case 1:									/* 阶段二：第一次捕获到下降沿 */
					{
						ccr1_cnt = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);/* 获取存放在CCR寄存器的值（捕获值CCR1） */
						Period_cnt1 = 	Period_cnt;				/* 获取计时器溢出次数1 */
						__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); /* 设置成上升沿捕获 */
						ic_flag = 2;							/* 捕获设置等待为第三个阶段 */
						break;
					}
					case 2:										/* 阶段三：第二次捕获到上升沿 */
					{
						ccr2_cnt = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);/* 取存放在CCR寄存器的值（捕获值CCR2） */
						Period_cnt2 = Period_cnt;				/* 获取计时器溢出次数2 */
						ic_flag = 0;							/* 捕获设置等待为第一个阶段 */
						end_flag = 1;							/* 完成一次捕获，将标志置1 */
						break;
					}
				}
			}
		}
}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
